﻿using Casamiel.API.Application.Models;
using Casamiel.Common;
using IdentityModel.Client;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using NLog;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using IdentityModel;
using Casamiel.Domain.Response;

namespace Casamiel.API.Controllers
{
	/// <summary>
	/// 
	/// </summary>
	[Produces("application/json")]
    [Route("api/Open")]
    [ApiVersionNeutral]
    [ApiController]
    [EnableCors("any")]
    public class OpenController : BaseController
    {
        private readonly NLog.ILogger logger = LogManager.GetLogger("OpenInfo");
        private readonly IHttpClientFactory _clientFactory;
        private readonly CasamielSettings _settings;
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="snapshot"></param>
        /// <param name="httpClientFactory"></param>
        public OpenController(IOptionsSnapshot<CasamielSettings> snapshot
            ,IHttpClientFactory httpClientFactory)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }

            _settings = snapshot.Value;
            _clientFactory = httpClientFactory;
        }
        /// <summary>
        /// getOpentoken
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[Action]")]
        public async Task<IActionResult> GetOpenToken([FromBody] OpenTokenReq data)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            // logger.Trace($"{this.LoginInfo.Item1}cc{this.LoginInfo.Item2}");
            using var client = _clientFactory.CreateClient();
            var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest {
                Address = $"{ _settings.IdentityUrl}/connect/token",

                ClientId = data.clientId,
                ClientSecret = data.clientsecret,
                Scope = _settings.ApiName
            }).ConfigureAwait(false);
            if (response.IsError) {
                logger.Error(response.Error);
                return new NotFoundResult();
            }
            var rsp = JsonConvert.DeserializeObject<AccessTokenRsp>(response.Raw);
            return Ok(rsp );

            //        var disco = await DiscoveryClient.GetAsync(_settings.IdentityUrl);
            //        if (disco.IsError)
            //        {
            //            logger.Error(disco.Error);
            //            return new NotFoundResult();
            //        }
            //        var json = JsonConvert.SerializeObject(data);
            //        try
            //        {
            //            var tokenClient = new TokenClient(disco.TokenEndpoint, data.clientId, data.clientsecret);
            //            string scope = _settings.ApiName;
            //            var tokenResponse = await tokenClient.RequestClientCredentialsAsync(scope);
            //var userAgent = Request.Headers["User-Agent"].ToString() == "" ? Request.Headers["UserAgent"].ToString() : Request.Headers["User-Agent"].ToString();
            //logger.Trace($"User-Agent[{userAgent}],ip[{Request.GetUserIp()}]");
            //            return new JsonResult(tokenResponse.Json);
            //        }
            //        catch (Exception ex)
            //        {
            //            logger.Error(ex.StackTrace);
            //            return BadRequest();
            //        }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[Action]")]
        public async Task<IActionResult> GetNewOpenToken([FromBody] OpenTokenReq data)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            // logger.Trace($"{this.LoginInfo.Item1}cc{this.LoginInfo.Item2}");


            TokenResponse response;
            using (var client = _clientFactory.CreateClient())
            {
                 response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
                {
                    Address = $"{ _settings.IdentityUrl}/connect/token",

                    ClientId = data.clientId,
                    ClientSecret = data.clientsecret,
                    Scope = _settings.ApiName
                }).ConfigureAwait(false);
                logger.Trace($"GetNewOpenToken:{JsonConvert.SerializeObject(response)}");
                if (response.IsError)
                {
                    logger.Error(response.Error);
                    return Ok(new { code = 9999 });
                }


                //   return Ok(new { code = 0, content = JsonConvert.DeserializeObject(response.Raw) });
            }
            var rsp = JsonConvert.DeserializeObject<AccessTokenRsp>(response.Raw);
            return Ok(new { code = 0, content = rsp });
        }

        /// <summary>
        /// GetToken (测试用)
        /// </summary>
        ///<param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[Action]")]
        public async Task<IActionResult> GetToken([FromForm] OpenTokenReq req)
        {
            if (req == null)
            {
                throw new ArgumentNullException(nameof(req));
            }

            if (string.IsNullOrEmpty(req.clientId)|| string.IsNullOrEmpty(req.clientsecret))
            {
                logger.Trace(Request.GetUserIp() + Request.GetAbsoluteUri() + Request.GetUserAgent());
                return new NotFoundResult();
            }
            var client = _clientFactory.CreateClient("");

            var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
            {
                Address = $"{ _settings.IdentityUrl}/connect/token",

                ClientId = req.clientId,
                ClientSecret =req.clientsecret,
                Scope = _settings.ApiName
            }).ConfigureAwait(false);
            if (response.IsError)
            {
                logger.Error(response.Error);
                return new NotFoundResult();
            }
            var rsp = JsonConvert.DeserializeObject<AccessTokenRsp>(response.Raw);
            return Ok(new { code = 0, content = rsp });
            //return Ok(response.Json);
            //var disco = await DiscoveryClient.GetAsync(_settings.IdentityUrl);
            //if (disco.IsError)
            //{
            //    Console.WriteLine(disco.Error);
            //    return new NotFoundResult(); 
            //}
            //logger.Warn($"{clientId}||{clientsecret}");

            //if(string.IsNullOrEmpty(clientId)|| string.IsNullOrEmpty(clientsecret))
            //{
            //    return BadRequest();
            //}
            //try
            //{
            //    var tokenClient = new TokenClient(disco.TokenEndpoint, clientId, clientsecret);
            //    string scope = _settings.ApiName;
            //    var tokenResponse = await tokenClient.RequestClientCredentialsAsync(scope);
            //    logger.Trace($"scope:{scope},User - Agent[{Request.Headers["User-Agent"]}],ip[{Request.GetUserIp()}]");
            //    return new JsonResult(tokenResponse.Json);
            //}
            //catch(Exception ex)
            //{
            //    logger.Error(ex.StackTrace);
            //    return BadRequest();
            //}
        }
    }
}